#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "my_list.h"

void initMyList(my_list *lst){
	lst->head = NULL;
	lst->tail = NULL;
}

void freeList(my_list *lst){
	Node *cur = lst->head;
	Node *temp = NULL;
	int i = 0;

	while (cur != NULL){
		for (i = 0; i < ELEMENTS_PER_NODE; ++i){
			if (cur->r[i].name != NULL)
				free(cur->r[i].name);
		}
		temp = cur;
		cur = cur->next;
		free(temp);
	}
}

int insertRecord(my_list *lst,unsigned id, char *name){
	Node *temp = lst->tail;  /*this is our work pointer*/
	char *tempName = NULL;
	int i = 0;
	int firstFlag = 0;

	if (lst->head == NULL) {  				/*the list is empty: populate it with a node and set tail to point to head*/
		firstFlag = 1;   				/*this flag spares a run of retrieve record on the next condition*/
		lst->head = (Node *)malloc(sizeof(Node));

		if (lst->head == NULL) return -7;  		/*mem. alloctaion failed*/

		else {
		lst->head->next = NULL; 			/*mark the end of the list*/
		lst->tail = lst->head;
		temp = lst->tail;   				/*set the work pointer as the tail which is the head in this case */
		}
	}

	if ((firstFlag) || (retrieveRecord(lst, id) == '\0')) {         /*if this list is empty or the id isn't in it we get to work...*/
		tempName = (char *)calloc(strlen(name)+1,sizeof(char));

		if (tempName == NULL) return -7;			/*checking mem. allocation*/

		strcpy(tempName, name);
		if (temp->r[ELEMENTS_PER_NODE - 1].id != 0){    	/*if the last node is full*/
			temp->next = (Node *)malloc(sizeof(Node)); 	/*create a new node at the end of the list*/
			if (temp->next == NULL) return -7;         	/*checking the mem. allocation*/
			temp = temp->next;				/*move temp to the new node*/
			temp->next = NULL;				/*mark the last node as the end of the list*/
			lst->tail = temp;                          	/*update lst's tail pointer*/
			i = 0;						/*set the index of the array to 0*/
		}
		else{							/*otherwise we need to find the first free cell*/
			i = 0;
			while (temp->r[i].id != 0)               	/*loop-over until we find one*/
				i++;
		}

		temp->r[i].id = id;					/*set the id*/
		temp->r[i].name = tempName;				/*set the name pointer to tempName allocated before*/
		return 1;						/*return success*/
	}
	else return 0;  						/*id is already in the database: return 0*/
}


int deleteRecord(my_list *lst, unsigned id){
	Node *cur = lst->head;
	Node *prev = NULL;
	int i = 0;
	int j = 0;

	while (cur != NULL){						                     /*loop to the end of the list*/
		for (i = 0; i < ELEMENTS_PER_NODE; ++i){		                     /*on each node run over all the records*/
			if (cur->r[i].id == id){			                     /*check if this is the record we are lookin for*/
				cur->r[i].id = 0;			                     /*mark the id as 0 == empty record*/
				free(cur->r[i].name); 			                     /*free the char *name from the mem.*/
				cur->r[i].name = NULL;					     /*mark the name pointer as NULL*/
				for (j = ELEMENTS_PER_NODE - 1; j > -1; --j){		     /*run over the tail node*/
					if (lst->tail->r[j].id != 0){			     /*find the last occupied record*/
						if ((cur == lst->tail) && (j < i)) return 1; /*if its before the deleted record-we deleted the last one*/
						cur->r[i].id = lst->tail->r[j].id;	     /*otherwise move the last record to the deleted record's pos.*/
						cur->r[i].name = lst->tail->r[j].name;
						lst->tail->r[j].id = 0;			     /*mark the moved record as empty*/
						lst->tail->r[j].name = NULL;
						break;
					}
				}
				if ((lst->head != lst->tail) && (j <= 0)){ 		     /*if we cleaned out the tail node*/
					while (prev->next != lst->tail){		     /*find the previous of tail*/
						prev = prev->next;
					}
					prev->next = NULL;	   			     /*mark this as the end of the list*/
					free(lst->tail);				     /*free the mem of the empty node*/
					lst->tail = prev;				     /*set the list's tail to the new tail*/
				}
				return 1;
			}
		}
		cur = cur->next;
	}
	return 0;									     /*we got here only if we didn't find the record to delete*/

}

char *retrieveRecord(my_list *lst, unsigned id){
	Node *temp = lst->head;
	int i = 0;

	while (temp != NULL){
		for (i = 0; i < ELEMENTS_PER_NODE; ++i){
			if (temp->r[i].id == id) return (temp->r[i].name);
		}
		temp = temp->next;
	}
	return '\0';
}

